/*
 * Copyright (c) 2020 HiHope Community.
 * Description: mq2 demo
 * Author: HiSpark Product Team.
 * Create: 2020-5-20
 */
#include <math.h>
#include <hi_early_debug.h>
#include <hi_task.h>
#include <hi_time.h>
#include <hi_adc.h>
#include <hi_stdlib.h>
#include <hi_watchdog.h>
#include <ssd1306_oled.h>
#include <hi_pwm.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include <app_demo_rtc.h>
#include <hisignalling_protocol.h>

//校准参数
//因为不同的传感器特性曲线不是很一致，因此，每一个传感器需要矫正这里这个参数才能使测量值很准确。
//当发现测试出来的重量偏大时，增加该数值。
//如果测试出来的重量偏小时，减小改数值。
//该值可以为小数,可参考误差1g调整10
#define GapValue 495

unsigned long Sensor_Read_Cat(void);
double Get_Sensor_Read_Cat(void);

unsigned long Sensor_Read_Dog(void);
double Get_Sensor_Read_Dog(void);
double cat_daily;
double dog_daily;

// hi_void gpio_init(void) {
// 	hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
//     hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
// }
double hx711_weight = 0;
hi_void *hi_hx711_task(hi_void* param)
{	
	(void) (param);
	gpio_init();
	//初始化GPIO11为GPIO输入，为传感器DT引脚
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_11,HI_GPIO_DIR_IN);
	//初始化GPIO11为GPIO输出，为传感器SCK引脚
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_12,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
	//初始化i2c,oled屏使用
    hi_i2c_init(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE); /* baudrate: 400kbps */
    hi_i2c_set_baudrate(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE);
	//oled初始化并显示对应信息
    while( HI_ERR_SUCCESS != oled_init()) ;
	oled_fill_screen(OLED_CLEAN_SCREEN);


    double base_data = 0;
	hi_u8 buf[10] = {0};
	hi_u8 buf_2[10] = {0};

	
	
    base_data = Get_Sensor_Read_Cat(); //获取基准值
    while (1)
    {
        hx711_weight = (Get_Sensor_Read_Cat() - base_data) / GapValue; //获取重量
		if((hx711_weight >= (weight_cat_new - 10)) && cat_close == HI_TRUE){
            hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE1);
            hi_udelay(500);  
            hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE0);
            hi_udelay(20000 - 500);
			second_cat = 0;
            cat_close = HI_FALSE;
		}
		cat_daily = cat_num * weight_cat_new - hx711_weight;
		//printf("Cat Food: %.2lf\r\n" ,hx711_weight);
		if(hx711_weight > 0)
		{
			oled_show_str(0,0, "Cat:",1);
			sprintf_s(buf,10,"%.2f",hx711_weight);
			oled_show_str(50,0, buf,1); //显示重量
			oled_show_str(120,0,"g",1);
			sprintf_s(buf_2,10,"%.2f",cat_daily);
			oled_show_str(50,2, buf_2, 1);
			oled_show_str(120,2,"g",1); 	
			
		}
		else{
			oled_show_str(0,0, "Cat:",1);
			sprintf_s(buf,10,"%.2f",0);
			oled_show_str(50,0, buf,1); //显示重量
			oled_show_str(120,0,"g",1);
			sprintf_s(buf_2,10,"%.2f",cat_daily);
			oled_show_str(50,2, buf_2, 1);
			oled_show_str(120,2,"g",1); 			
		}
		hi_sleep(200);  

    }
}

double hx711_weight_2 = 0;
hi_void *hi_hx711_task_2(hi_void* param)
{	
	(void) (param);
	hi_gpio_init();
	//初始化GPIO7为GPIO输入，为传感器DT引脚
    hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_7,HI_GPIO_DIR_IN);
	//初始化GPIO8为GPIO输出，为传感器SCK引脚
    hi_io_set_func(HI_IO_NAME_GPIO_8, HI_IO_FUNC_GPIO_8_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_8,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);
	//初始化i2c,oled屏使用
    //hi_i2c_init(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE); /* baudrate: 400kbps */
    //hi_i2c_set_baudrate(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE);
	//oled初始化并显示对应信息
    // while( HI_ERR_SUCCESS != oled_init()) ;
	// oled_fill_screen(OLED_CLEAN_SCREEN);

    double base_data = 0;
	hi_u8 buf_3[10] = {0};
	hi_u8 buf_4[10] = {0};

    base_data = Get_Sensor_Read_Dog(); //获取基准值
     while (1)
     {
        hx711_weight_2 = (Get_Sensor_Read_Dog() - base_data) / GapValue; //获取重量
        if((hx711_weight_2 >= (weight_dog_new - 10)) && dog_close == HI_TRUE){
            hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE1);
            hi_udelay(1000);  
            hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE0);
            hi_udelay(20000 - 1000);    
            dog_close = HI_FALSE;
			second_dog = 0;
        }
		dog_daily = dog_num * weight_dog_new - hx711_weight_2; 
		if(hx711_weight_2 > 0)
		{
			oled_show_str(0,4, "Dog:",1);
			sprintf_s(buf_3,10,"%.2f",hx711_weight_2);
			oled_show_str(50,4, buf_3,1);
			oled_show_str(120,4, "g",1);
			sprintf_s(buf_4,10,"%.2f",dog_daily);
			oled_show_str(50,6, buf_4, 1);
			oled_show_str(120,6, "g",1);		
		} 
		else{
			oled_show_str(0,4, "Dog:",1);
			sprintf_s(buf_3,10,"%.2f",0);
			oled_show_str(50,4, buf_3,1);
			oled_show_str(120,4, "g",1);
			sprintf_s(buf_4,10,"%.2f",dog_daily);
			oled_show_str(50,6, buf_4, 1);
			oled_show_str(120,6, "g",1);	
		}
		hi_sleep(200);  
		
     }
}


unsigned long Sensor_Read_Cat(void)
{
	unsigned long value = 0;
	unsigned char i = 0;
	hi_gpio_value input = 0;
	hi_udelay(2);
	//时钟线拉低 空闲时时钟线保持低电位
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
	hi_udelay(2);	
	hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
	//等待AD转换结束
	while(input)
    {
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
    }
	for(i=0;i<24;i++)
	{
		//时钟线拉高 开始发送时钟脉冲
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,1);
		hi_udelay(2);
		//左移位 右侧补零 等待接收数据
		value = value << 1;
		//时钟线拉低
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
		hi_udelay(2);
		//读取一位数据
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
		if(input){
			value ++;
        }
	}
	//第25个脉冲
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,1);
	hi_udelay(2);
	value = value^0x800000;	
	//第25个脉冲结束
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);	
	hi_udelay(2);	
	return value;
}


unsigned long Sensor_Read_Dog(void)
{
	unsigned long value = 0;
	unsigned char i = 0;
	hi_gpio_value input = 0;
	hi_udelay(2);
	//时钟线拉低 空闲时时钟线保持低电位
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_7,0);
	hi_udelay(2);	
	hi_gpio_get_input_val(HI_IO_NAME_GPIO_7,&input);
	//等待AD转换结束
	while(input)
    {
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_7,&input);
    }
	for(i=0;i<24;i++)
	{
		//时钟线拉高 开始发送时钟脉冲
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,1);
		hi_udelay(2);
		//左移位 右侧补零 等待接收数据
		value = value << 1;
		//时钟线拉低
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);
		hi_udelay(2);
		//读取一位数据
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_7,&input);
		if(input){
			value ++;
        }
	}
	//第25个脉冲
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,1);
	hi_udelay(2);
	value = value^0x800000;	
	//第25个脉冲结束
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);	
	hi_udelay(2);	
	return value;
}

double Get_Sensor_Read_Cat(void)
{
  	double sum = 0;    // 为了减小误差，一次取出10个值后求平均值。
  	for (int i = 0; i < 3; i++) // 循环的越多精度越高，当然耗费的时间也越多
    	sum += Sensor_Read_Cat();  // 累加
  	return (sum/3); // 求平均值进行均差

}

double Get_Sensor_Read_Dog(void)
{
  	double sum = 0;    // 为了减小误差，一次取出10个值后求平均值。
  	for (int i = 0; i < 3; i++) // 循环的越多精度越高，当然耗费的时间也越多
    	sum += Sensor_Read_Dog();  // 累加
  	return (sum/3); // 求平均值进行均差

}


#define HX711_DEMO_TASK_STAK_SIZE  		(1024*4)
#define HX711_DEMO_TASK_PRIORITY		(28)
#define HX711_DEMO_TASK_NAME			((hi_char*)"hx711 task")
hi_u32 g_hx711_demo_task_id;
hi_u32 hx711_task(hi_void)
{
    hi_u32 ret = 0;
    hi_task_attr attr = {0};

    attr.stack_size = HX711_DEMO_TASK_STAK_SIZE;
    attr.task_prio  = HX711_DEMO_TASK_PRIORITY;
    attr.task_name  = HX711_DEMO_TASK_NAME;

    ret = hi_task_create(&g_hx711_demo_task_id, &attr, hi_hx711_task, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create hx711 task\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}

#define HX711_DEMO_TASK_STAK_SIZE_2 		(1024*4)
#define HX711_DEMO_TASK_PRIORITY_2		(28)
#define HX711_DEMO_TASK_NAME_2			((hi_char*)"hx711 task_2")
hi_u32 g_hx711_demo_task_id_2;
hi_u32 hx711_task_2(hi_void)
{
    hi_u32 ret = 0;
    hi_task_attr attr = {0};

    attr.stack_size = HX711_DEMO_TASK_STAK_SIZE_2;
    attr.task_prio  = HX711_DEMO_TASK_PRIORITY_2;
    attr.task_name  = HX711_DEMO_TASK_NAME_2;

    ret = hi_task_create(&g_hx711_demo_task_id_2, &attr, hi_hx711_task_2, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create hx711 task\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}